#ifndef VM_H
#define VM_H

#include "utility/Types.h"
#include "Utils.h"
#include "Mutex.h"
#include "Mmu.h"

void InitVM();

typedef struct BitMap {
    uint32_t count;     // how many pages this bitmap can hold
    uint8_t* bitmap;    // bitmap data, 1 means used, 0 means free
    uint32_t pageSize;  // size per page (byte)
    uint32_t start;     // start physical address
    uint32_t size;      // total memory size (byte)
    MutexType* mutex;
} BitMapType;

typedef struct MemoryMap{
    void* virtualStart;
    void* virtualEnd;
    void* physicalStart;
    uint32_t permission;
} MemoryMapType;



uint32_t GetBytesCount(uint32_t size);
void InitBitMap(BitMapType* bitmap, uint8_t* bits, uint32_t start, uint32_t size, uint32_t pageSize);
uint8_t GetBitMapBit(BitMapType* bitmap, uint32_t index);
void SetBitMapBit(BitMapType* bitmap, uint32_t index, uint32_t count, bool bit);
bool IsBitSet(BitMapType* bitmap, uint32_t index);
int AllocateBitMap(BitMapType* bitmap, bool value, uint32_t count);
void CreateKernelTable(void);

PTEType* FindPTE(PDEType* pdeTable, uint32_t vaddr, bool create);

int CreateTaskPageDirectoryTable(void);
uint32_t AllocateMemoryForCurrentTask(uint32_t vaddr, uint32_t size, int perm);
uint32_t AllocateKernelPage(void);
uint32_t AllocateMemory(uint32_t pdeAddress, uint32_t vaddr, uint32_t size, uint32_t perm);
void FreeMemoryPage(uint32_t vaddr);

uint32_t CopyUserVirtualMemoryAndPageTable(uint32_t pageDir);
void FreeUserVirtualMemoryAndPageTable(uint32_t pageDir);
int CopyDataFromOtherPageDir(uint32_t to, uint32_t pageDir, uint32_t from, uint32_t size);

uint32_t GetPhysicalAddress(uint32_t pageDir, uint32_t vaddr);

#endif VM_H